﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using Reactor.Configuration;

namespace Reactor.Providers
{
    public interface IConfigurationDataProvider
    {
        /// <summary>
        /// Gets all configuration elements from the underlying configuration store.
        /// </summary>
        /// <returns></returns>
        ConfigurationElement[] GetAllElements();

        /// <summary>
        /// Stores the configuration value at the specified key.
        /// </summary>
        /// <param name="key">The key.</param>
        /// <param name="value">The value.</param>
        void StoreConfigurationValue(string key, string value);
    }

    public class SqlConfigurationDataProvider : IConfigurationDataProvider
    {
        private readonly string _connectionString;
        private const string ConfigKey = "ConfigKey";
        private const string ConfigValue = "ConfigValue";

        /// <summary>
        /// Initializes a new instance of the <see cref="SqlConfigurationDataProvider"/> class.
        /// </summary>
        /// <param name="connectionString">The connection string this instance is to use.</param>
        public SqlConfigurationDataProvider(string connectionString)
        {
            if (string.IsNullOrEmpty(connectionString))
                throw new ArgumentNullException("connectionString");

            _connectionString = connectionString;
        }

        #region Implementation of IConfigurationDataProvider

        /// <summary>
        /// Gets all configuration elements from the underlying configuration store.
        /// </summary>
        /// <returns>Array of configuration elements found the underlying SQL database.</returns>
        public ConfigurationElement[] GetAllElements()
        {
            var elements = new List<ConfigurationElement>();

            using (var sqlConnection = new SqlConnection(_connectionString))
            {
                using (var cmd = new SqlCommand("dbo.rsb_GetAllConfigurationElements"))
                {
                    cmd.CommandType = CommandType.StoredProcedure;
                    sqlConnection.Open();
                    cmd.Connection = sqlConnection;

                    using (var rdr = cmd.ExecuteReader(CommandBehavior.CloseConnection))
                    {
                        if(rdr != null)
                        {
                            while (rdr.Read())
                            {
                                var key = rdr.GetString(rdr.GetOrdinal(ConfigKey));
                                var value = rdr.GetString(rdr.GetOrdinal(ConfigValue));

                                if (!elements.Any(e => e.Key == key))
                                    elements.Add(new ConfigurationElement {Key = key, Value = value});
                            }
                        }
                    }
                }
            }

            return elements.ToArray();
        }

        /// <summary>
        /// Stores the configuration value at the specified key.
        /// </summary>
        /// <param name="key">The key.</param>
        /// <param name="value">The value.</param>
        public void StoreConfigurationValue(string key, string value)
        {
            using (var sqlConnection = new SqlConnection(_connectionString))
            {
                using (var cmd = new SqlCommand("dbo.rsb_SaveConfigurationElement"))
                {
                    cmd.CommandType = CommandType.StoredProcedure;
                    sqlConnection.Open();
                    cmd.Connection = sqlConnection;

                    cmd.Parameters.AddWithValue(ConfigKey, key);
                    cmd.Parameters.AddWithValue(ConfigValue, value);
                    cmd.ExecuteNonQuery();
                }
            }
        }

        #endregion
    }
}
